"""
书法评价系统启动工具
自动检查依赖，配置环境，并启动评价系统
"""
import os
import sys
import subprocess
import socket
import time
import atexit
from flask import request, jsonify, render_template
from werkzeug.utils import secure_filename
from datetime import datetime

# 导入警告抑制模块
try:
    import suppress_warnings
except ImportError:
    print("警告抑制模块不可用，您可能会看到一些非关键警告")

# 端口锁文件路径
PORT_LOCKFILE = 'port_8080.lock'
DEFAULT_PORT = 8080

# 导入风格识别器
from style_classifier import StyleClassifier

def check_dependencies():
    """检查所需的依赖库是否已安装"""
    required_modules = [
        'flask', 'numpy', 'cv2', 'scipy', 
        'pywt', 'matplotlib', 'skimage'
    ]
    
    missing_modules = []
    for module in required_modules:
        try:
            if module == 'cv2':
                __import__('cv2')
            else:
                __import__(module)
        except ImportError:
            missing_modules.append(module)
    
    if missing_modules:
        print(f"缺少以下依赖库: {', '.join(missing_modules)}")
        return False
    
    return True

def install_dependencies():
    """安装所需的依赖库"""
    print("正在安装依赖...")
    subprocess.run([sys.executable, "-m", "pip", "install", "-r", "requirements.txt"])

def ensure_directories():
    """确保必要的目录存在"""
    directories = ['templates', 'uploads', 'models']
    for directory in directories:
        if not os.path.exists(directory):
            print(f"创建目录: {directory}")
            os.makedirs(directory)

def initialize_models():
    """初始化书法风格模型"""
    print("初始化书法风格模型...")
    try:
        # 导入并初始化风格模型
        from style_models import (
            get_style_model, 
            STYLE_REGULAR, 
            STYLE_RUNNING,
            STYLE_CURSIVE,
            STYLE_CLERICAL,
            STYLE_SEAL,
            SUPPORTED_STYLES
        )
        
        # 为每种风格创建并保存默认模型
        for style in SUPPORTED_STYLES:
            get_style_model(style)
        
        print("风格模型初始化完成")
    except Exception as e:
        print(f"初始化风格模型时出错: {e}")

def is_port_in_use(port):
    """检查端口是否被占用"""
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        return s.connect_ex(('localhost', port)) == 0

def create_port_lock():
    """创建端口锁文件，防止多个实例同时运行"""
    try:
        with open(PORT_LOCKFILE, 'w') as f:
            f.write(str(os.getpid()))
        print(f"已创建端口锁文件: {PORT_LOCKFILE} (PID: {os.getpid()})")
        
        # 注册程序退出时删除锁文件
        atexit.register(remove_port_lock)
    except Exception as e:
        print(f"创建端口锁文件时出错: {e}")

def remove_port_lock():
    """移除端口锁文件"""
    try:
        if os.path.exists(PORT_LOCKFILE):
            os.remove(PORT_LOCKFILE)
            print(f"已删除端口锁文件: {PORT_LOCKFILE}")
    except Exception as e:
        print(f"删除端口锁文件时出错: {e}")

def is_own_lockfile():
    """检查锁文件是否是自己创建的"""
    if os.path.exists(PORT_LOCKFILE):
        try:
            with open(PORT_LOCKFILE, 'r') as f:
                pid = int(f.read().strip())
                # 如果PID与当前进程相同，则是自己的锁文件
                return pid == os.getpid()
        except (ValueError, IOError):
            pass
    return False

def start_app():
    """启动Flask应用程序"""
    PORT = DEFAULT_PORT  # 固定使用8080端口
    
    # 检查是否禁用热重载
    no_reload = "FLASK_DEBUG" in os.environ and os.environ["FLASK_DEBUG"] == "0"
    
    # 只在主进程中检查端口
    if not is_own_lockfile():
        # 检查端口是否被占用
        if is_port_in_use(PORT):
            print(f"\n错误: 端口 {PORT} 已被其他程序占用")
            print("请手动终止占用该端口的进程后重试，或者使用以下命令查看占用端口的进程:")
            print(f"  lsof -i :{PORT}")
            print("然后使用以下命令终止进程:")
            print("  kill <PID>")
            return
        
        # 创建端口锁
        create_port_lock()
        
        # 在热重载模式下发出警告
        if not no_reload:
            print("\n注意: Flask正在热重载模式下运行，可能导致多个进程启动。")
            print("如果遇到端口问题，请使用以下命令禁用热重载:")
            print("  python run.py --no-reload")
    
    print("\n正在启动书法评价系统...")
    print(f"请在浏览器中访问: http://localhost:{PORT}")
    print("按 Ctrl+C 停止服务器\n")
    
    os.environ["FLASK_APP"] = "app.py"
    
    try:
        from app import app
        app.run(debug=not no_reload, host='0.0.0.0', port=PORT, use_reloader=not no_reload)
    except Exception as e:
        print(f"启动应用程序时出错: {e}")
    finally:
        # 确保退出时删除锁文件
        if is_own_lockfile():
            remove_port_lock()

def main():
    """
    主函数
    
    如果需要禁用Flask的热重载机制，可以使用以下命令:
    $ FLASK_DEBUG=0 python run.py
    或
    $ python run.py --no-reload
    """
    print("=" * 50)
    print("书法评价系统启动工具")
    print("=" * 50)
    
    # 解析命令行参数
    no_reload = False
    for arg in sys.argv:
        if arg == '--no-reload':
            no_reload = True
            os.environ["FLASK_DEBUG"] = "0"
            print("已禁用Flask热重载模式")
    
    # 检查并删除可能遗留的锁文件
    if os.path.exists(PORT_LOCKFILE):
        try:
            with open(PORT_LOCKFILE, 'r') as f:
                pid = int(f.read().strip())
                # 检查PID是否还在运行
                try:
                    os.kill(pid, 0)  # 发送空信号检查进程是否存在
                    print(f"警告: 发现已有书法评价系统实例正在运行 (PID: {pid})")
                    print("如果需要启动新实例，请先停止现有实例，或删除锁文件:")
                    print(f"  rm {PORT_LOCKFILE}")
                    sys.exit(1)
                except OSError:
                    # 进程不存在，可以安全地删除锁文件
                    print(f"发现过期的锁文件，正在删除: {PORT_LOCKFILE}")
                    os.remove(PORT_LOCKFILE)
        except (ValueError, IOError) as e:
            # 锁文件格式不正确，删除它
            print(f"发现无效的锁文件，正在删除: {PORT_LOCKFILE}")
            os.remove(PORT_LOCKFILE)
    
    # 检查依赖
    if not check_dependencies():
        user_input = input("是否安装缺少的依赖? (y/n): ")
        if user_input.lower() == 'y':
            install_dependencies()
        else:
            print("缺少必要的依赖，无法启动系统")
            sys.exit(1)
    
    # 确保必要的目录存在
    ensure_directories()
    
    # 初始化模型
    initialize_models()
    
    # 初始化风格分类器
    style_classifier = StyleClassifier()
    
    # 启动应用
    start_app()

if __name__ == "__main__":
    main() 